//
//  main.m
//  08-iOS9新特性(Nulllability, 泛型,_kindOf)
//
//  Created by Snow on 16/7/13.
//  Copyright © 2016年 Snow. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Truck.h"
#import "Student.h"

int main(int argc, const char * argv[]) {
    Person *per = [[Person alloc] init];
    // 1.
    //nonull 修饰的属性 对应getter setter方法
//    NSString *objc = nil;
//    per.name = objc;
//    [per setName:objc];
//    per.name = @"zhangsan";
//    [per name];
    
    per.name = nil;
    [per setName:nil];
    per.name = @"zhangsan";
    [per name];
    
  // nullable 修饰的属性 对应的getter setter方法
    //per setGender:<#(NSString * _Nullable)#>
    //[per gender];
    per.gender = nil;
    
    //null_resettable 懒加载
//    [per setFriends:<#(NSArray * _Nullable)#>];
//    [per friends];
    
    
    //2.泛型
    //带泛型的容器(规定了容器中所存储的类型)
    //声明一个可变数组, 内部存放的都是字符串nsstring
    //好处:
        //1.数组中添加其他类型 会有警告
        //2.数组获取出来的类型不在是id类型 对应变成声明时的类型
        //3.泛型会改变类的一些方法 使与声明的类型相同
    
    //(轻量级泛型)
    NSMutableArray<NSString *> *aray = [NSMutableArray arrayWithObjects:@"123", nil];
//    aray.firstObject.length
    [aray addObject:@""];
//    [aray addObject:@20];
//    [aray addObject:per];
//    aray addObject:<#(nonnull NSString *)#>
    NSInteger integer = [aray objectAtIndex:0].length;
    
    //带泛型字典
    NSMutableDictionary<NSString *, NSString *> *dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"zhangsan", @"name", nil];
//    [dic objectForKey:<#(nonnull id)#>]
//    [dic objectForKey:@"name"].length   此时是id类型 无法调属性
//    [dic objectForKey:<#(nonnull NSString *)#>]
    NSInteger interger = [dic objectForKey:@"name"].length;
    //此时是NSstring类型 可以调用属性
//    [dic setObject:<#(nonnull NSString *)#> forKey:<#(nonnull id<NSCopying>)#>]
    
    //自定义泛型
    Truck<Person *> *truckPer = [[Truck alloc] init];
    [truckPer addObject:per];
    [truckPer firstObject];
    
    Student *stu = [[Student alloc] init];
    stu.stuNumber = @"0001";
    Truck<Student *> *truckStu = [[Truck alloc] init];
    [truckStu addObject:stu];
    
    [truckStu addObject:per];
    [truckPer addObject:stu];
    
    //协变性
    Truck *truck = nil;
    Truck<NSArray *> *truck1 = nil;
    Truck<NSMutableArray *> *truck2 = nil;
    
    //大类型(任意类型)可以给有泛型的赋值
    truck = truck1;
    truck = truck2;
    truck1 = truck;
    truck2 = truck;
    //__covariant 协变性 子类可以给父类赋值时自动强转
    //Truck<NSArray *> Truck<NSMutableArray *>
    truck1 = truck2;
    //逆变__contravariant 父类给子类赋值 自动强转
    truck2 = truck1;
    
    
    //3.__kindOf
    //加kindOf修饰后 返回的类型及其子类型 都可以接受这个返回值
    Truck *truckKindof = [[Truck alloc] init];
//    NSMutableArray *arr = [truckKindof returnArray];
    NSMutableArray *arr = (NSMutableArray *)[truckKindof returnArray];
    NSArray *arr1 = [truckKindof returnArray];
    NSMutableArray *arr2 = (NSMutableArray *)[truckKindof returnArray];
    
    //
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    return 0;
}
